page.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. "use client";
  2. import {
  3. claimActivityReward,
  4. ContinuousCfgItem,
  5. ContinuousListItem,
  6. ContinuousResult,
  7. ContinuousRewardItem,
  8. getContinuousRechargeInfo,
  9. } from "@/api/activity";
  10. import CutDown from "@/components/CutDown";
  11. import GlobalNotify from "@/components/ModalPopup/GlobalNotifyModal";
  12. import { ClaimActiveErrorMap } from "@/enums";
  13. import { useRouter } from "@/i18n/routing";
  14. import { formatAmount } from "@/utils/index";
  15. import { Toast } from "antd-mobile";
  16. import BigNumber from "bignumber.js";
  17. import clsx from "clsx";
  18. import { useTranslations } from "next-intl";
  19. import { useSearchParams } from "next/navigation";
  20. import React from "react";
  21. import styles from "./page.module.scss";
  22. interface ListItem {
  23. dayId: number;
  24. data: ContinuousListItem;
  25. }
  26. interface RewardItem {
  27. dayId: number;
  28. data: ContinuousRewardItem[];
  29. }
  30. //"#297fcf"
  31. const DayItem = ({
  32. data,
  33. idx,
  34. onClaim,
  35. onEnd,
  36. }: {
  37. data: ContinuousCfgItem;
  38. idx: number;
  39. onClaim: (data: ContinuousCfgItem) => void;
  40. onEnd?: Function;
  41. }) => {
  42. const dayColor = React.useMemo(() => {
  43. return ["#12940f", "#297fcf", "#ec3920"][idx % 3];
  44. }, [idx]);
  45. const doClaim = () => {
  46. if (onClaim && typeof onClaim === "function") {
  47. onClaim(data);
  48. }
  49. };
  50. return (
  51. <div className={styles.dayItemBox}>
  52. {data.id >= 2 && data.isCanClaim && (
  53. <div className="mb-[.1rem] flex flex-row justify-center">
  54. <div className={styles.canGet}>Grande Prêmio Disponível</div>
  55. </div>
  56. )}
  57. {!!data.end_at && (
  58. <div className="item-center mb-[.1rem] flex flex-row justify-center">
  59. <CutDown
  60. endTime={data.end_at - Date.now() / 1000}
  61. itemBgColor="rgba(255,255,255,.4)"
  62. onEnd={onEnd}
  63. ></CutDown>
  64. </div>
  65. )}
  66. <div className={styles.premioItem}>
  67. <div className={styles.premioItemDay}>
  68. <span style={{ color: dayColor }}>{data.days}</span>
  69. </div>
  70. <div className="flex flex-1 flex-col justify-between">
  71. <div className="text-[.16rem] font-bold">
  72. Recarga contínua por {data.days} dias
  73. </div>
  74. <div className="flrx-row flex items-center justify-between">
  75. <div>Recompensa de login</div>
  76. <div
  77. className={clsx(styles.premioItemBtn, {
  78. [styles.disabled]: !data.isCanClaim,
  79. })}
  80. onClick={doClaim}
  81. >
  82. {data.is_sign === 0 ? "Recebido" : "Receber"}
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. );
  89. };
  90. const Page = () => {
  91. const t = useTranslations();
  92. const query = Object.fromEntries(useSearchParams());
  93. const [data, setData] = React.useState<ContinuousResult>({} as ContinuousResult);
  94. const router = useRouter();
  95. const dayContainer = React.useRef<HTMLDivElement>(null);
  96. const [amount, setAmount] = React.useState<any>({});
  97. const [visible, setVisible] = React.useState<boolean>(false);
  98. const act = React.useMemo(() => {
  99. if (!data || data.type === 11) return 0;
  100. return 1;
  101. }, [data]);
  102. React.useEffect(() => {
  103. getData();
  104. // eslint-disable-next-line react-hooks/exhaustive-deps
  105. }, [query.activity_id]);
  106. const getData = async () => {
  107. const res = await getContinuousRechargeInfo({ activity_id: Number(query.activity_id) });
  108. if (res.code === 200) {
  109. setData(res.data);
  110. }
  111. };
  112. const list = React.useMemo<ListItem[]>(() => {
  113. if (!data?.list?.list) {
  114. return [];
  115. }
  116. const result: ListItem[] = [] as ListItem[];
  117. Object.keys(data?.list?.list).forEach((key: string) => {
  118. const item = data?.list?.list[key as any];
  119. const key1 = Object.keys(item)[0];
  120. result.push({ dayId: Number(key), data: item[key1 as any] });
  121. });
  122. return result.sort((a, b) => a.dayId - b.dayId);
  123. }, [data?.list?.list]);
  124. const reward_list = React.useMemo<RewardItem[]>(() => {
  125. if (!data?.list?.reward_list) {
  126. return [];
  127. }
  128. const result: RewardItem[] = [] as RewardItem[];
  129. Object.keys(data?.list?.reward_list).forEach((key: string) => {
  130. const item = data?.list?.reward_list[key as any];
  131. const res2: ContinuousRewardItem[] = [];
  132. Object.keys(item).forEach((key2: string) => {
  133. const item2 = item[key2 as any];
  134. res2.push(item2);
  135. });
  136. result.push({ dayId: Number(key), data: res2 });
  137. });
  138. return result;
  139. }, [data?.list?.reward_list]);
  140. const waitList = React.useMemo<ContinuousCfgItem[]>(() => {
  141. if (!data?.list?.config_list) return [];
  142. const result = [] as ContinuousCfgItem[];
  143. data?.list?.config_list.forEach((item) => {
  144. if (
  145. item.is_sign === 0 ||
  146. item.is_suss === 1 ||
  147. !(item.start_at * 1000 < Date.now() && item.end_at * 1000 > Date.now())
  148. ) {
  149. item.isCanClaim = false;
  150. } else {
  151. item.isCanClaim = true;
  152. }
  153. result.push(item);
  154. });
  155. return result.sort((a, b) => a.days - b.days);
  156. }, [data?.list?.config_list]);
  157. const goDeposit = () => {
  158. router.push("/deposit");
  159. };
  160. const doClaim = async (data: ContinuousCfgItem) => {
  161. if (!query.activity_id) {
  162. Toast.show({ content: "Missing activity ID" });
  163. return;
  164. }
  165. if (!data.is_sign) return;
  166. try {
  167. const res = await claimActivityReward({
  168. activity_id: Number(query.activity_id),
  169. id: data.days,
  170. });
  171. if (res.code === 200 && res?.data?.code === 1) {
  172. const amountObj: any = {};
  173. if (res?.data?.reward) {
  174. res?.data?.reward.forEach((item: any) => {
  175. amountObj[`coin_${item.coin_type}`] = formatAmount(item.amount);
  176. });
  177. }
  178. if (res?.data?.extra_reward) {
  179. res?.data?.extra_reward.forEach((item: any) => {
  180. amountObj[`coin_${item.coin_type}`] = formatAmount(
  181. new BigNumber(amountObj[`coin_${item.coin_type}`] || 0)
  182. .plus(item.amount)
  183. .toString()
  184. );
  185. });
  186. }
  187. if (Object.keys(amountObj).length > 0) {
  188. setVisible(true);
  189. setAmount(amountObj);
  190. }
  191. getData();
  192. } else {
  193. throw new Error(ClaimActiveErrorMap.get(res.data.code) || t(`code.400`));
  194. }
  195. } catch (error: any) {
  196. if (error) {
  197. Toast.show({
  198. content: error.message || error.toString(),
  199. maskClickable: false,
  200. });
  201. }
  202. }
  203. };
  204. const doGoLinkActivity = (type: 11 | 13) => {
  205. if (type === data.type || !data.associated_activity_id) return;
  206. router.replace({
  207. pathname: "/rechargeproxy",
  208. query: { activity_id: data.associated_activity_id },
  209. });
  210. };
  211. return (
  212. <div className={clsx(styles.continuePage)}>
  213. <div className={styles.container}>
  214. <div className={styles.top}>
  215. <img className={styles.img} src="/proxyRecharge/top.png" alt="" />
  216. {act === 0 && (
  217. <div className={styles.recharge} onClick={goDeposit}>
  218. RECARGA
  219. </div>
  220. )}
  221. </div>
  222. <div className={styles.content}>
  223. <div className={styles.tip}>
  224. <div
  225. className={clsx(styles.text, {
  226. [styles.active]: act === 0,
  227. })}
  228. onClick={() => doGoLinkActivity(11)}
  229. >
  230. Meu login
  231. </div>
  232. <div
  233. className={clsx(styles.text, {
  234. [styles.active]: act === 1,
  235. })}
  236. onClick={() => doGoLinkActivity(13)}
  237. >
  238. Login de amigo
  239. </div>
  240. </div>
  241. <div className={styles.inner}>
  242. <div
  243. className={clsx(styles.innerContainer, {
  244. [styles.innerContainer1]: act === 1,
  245. })}
  246. >
  247. {!!list?.length && (
  248. <div
  249. className={clsx(styles.stageBox, {
  250. [styles.stageBox1]: act === 1,
  251. })}
  252. >
  253. {list.map((item, idx) => {
  254. return (
  255. <div
  256. key={item.dayId}
  257. className={clsx(styles.stageItem, {
  258. [styles.unlock]: item.data.is_sign === 1,
  259. [styles.lock]: item.data.is_sign === 0,
  260. })}
  261. >
  262. <div className={styles.stageText}>
  263. <div>Para ser</div>
  264. <div className="mt-[.03rem]">concluído</div>
  265. </div>
  266. <div className={styles.stageText2}>
  267. <span>recarga</span>
  268. <div className={styles.stageText2Num}>
  269. {item.data.pay_num}
  270. </div>
  271. </div>
  272. <div className={clsx(styles.stageImg)}></div>
  273. <div className={styles.stageDay}>
  274. Dia {item.dayId}
  275. </div>
  276. </div>
  277. );
  278. })}
  279. </div>
  280. )}
  281. {/* {!!list?.length && (
  282. <div className={styles.daybox}>
  283. <div className={styles.dayContainer} ref={dayContainer}>
  284. {list.map((item: any) => {
  285. return (
  286. <div
  287. key={item.dayId}
  288. className={clsx(styles.dayItem, {
  289. [styles.active]: item.data.is_sign,
  290. })}
  291. >
  292. <div className={styles.dayItemText}>
  293. {item.dayId} dia
  294. </div>
  295. <div className={styles.dayitemTextActive}>
  296. <img
  297. src={`/continuous/s${item.data.id}.png`}
  298. alt=""
  299. />
  300. <div className="flex flex-row items-end text-[#dbc6ff]">
  301. <span className="relative top-[1px] mt-[2px] text-[.13rem]">
  302. {item.dayId}
  303. </span>
  304. <span>dia</span>
  305. </div>
  306. <div>recarga</div>
  307. <div className="mt-[.03rem] w-[100%] overflow-hidden text-ellipsis text-[#ffb400]">
  308. {item?.data?.pay_num}
  309. </div>
  310. </div>
  311. </div>
  312. );
  313. })}
  314. </div>
  315. </div>
  316. )} */}
  317. {!!waitList.length && (
  318. <div className={styles.premio}>
  319. <div
  320. className={clsx(styles.premioTitle, {
  321. [styles.premioTitle1]: act === 1,
  322. })}
  323. >
  324. {act === 1 && (
  325. <div className={styles.premioTitleText}>
  326. <div>AMIGO ENTRAR PARA</div>
  327. <div>RECEBER CORTESIA</div>
  328. </div>
  329. )}
  330. {act === 0 && (
  331. <div className={styles.premioTitleText}>
  332. <div>ENTRAR E RECEBER CORTESIA</div>
  333. </div>
  334. )}
  335. </div>
  336. <div className={styles.premioContainer}>
  337. <div className={styles.premioContent}>
  338. {waitList.map((item, idx: number) => {
  339. return (
  340. <DayItem
  341. key={item.days}
  342. data={item}
  343. idx={idx}
  344. onClaim={doClaim}
  345. onEnd={getData}
  346. ></DayItem>
  347. );
  348. })}
  349. </div>
  350. </div>
  351. </div>
  352. )}
  353. <div className={styles.cfgbox}>
  354. <div className={styles.cfgContainer} ref={dayContainer}>
  355. <div className={styles.cfgHeader}>
  356. <div>
  357. Dias de
  358. <br />
  359. depósito
  360. </div>
  361. <div>
  362. Requisitos da <br />
  363. atividade
  364. </div>
  365. {data.type === 11 && (
  366. <div>
  367. Valor do
  368. <br />
  369. bônus
  370. </div>
  371. )}
  372. {data.type === 13 && (
  373. <div>
  374. Recompensas <br />
  375. de Agente
  376. </div>
  377. )}
  378. </div>
  379. {reward_list.map((item) => {
  380. return (
  381. <div key={item.dayId} className={styles.cfgItem}>
  382. <div className={styles.cfgItemName}>
  383. Recarga contínua por{" "}
  384. <div className="text-[#faab00]">
  385. {item.dayId}dias
  386. </div>
  387. </div>
  388. <div className="flex-1">
  389. {item.data.map((item2, idx) => {
  390. return (
  391. <div
  392. key={item2.id}
  393. className={styles.cfgItemChild}
  394. >
  395. <div>
  396. Mais de {item2.target_num} por
  397. dia
  398. </div>
  399. <div>{item2.target_reward}</div>
  400. </div>
  401. );
  402. })}
  403. </div>
  404. </div>
  405. );
  406. })}
  407. </div>
  408. </div>
  409. <div className={styles.introbox}>
  410. <div className={styles.introContainer}>
  411. <div className={styles.introTitle}>
  412. <span className={styles.introTitleText}>
  413. Regras de Atividade
  414. </span>
  415. </div>
  416. <div className="h-[.2rem]"></div>
  417. <ul className={styles.introboxDesc}>
  418. <li>
  419. Os prémios são reclamados no mesmo dia das 23:00 às
  420. 23:50
  421. </li>
  422. <li>
  423. O bônus desta promoção deve ser solicitado dentro do
  424. período promocional. Solicitações feitas após o prazo
  425. serão consideradas como desistência automática.
  426. </li>
  427. <li>
  428. Ao participar desta promoção, você concorda em cumprir
  429. os Termos e Regras da Promoção.
  430. </li>
  431. </ul>
  432. <div className="mt-[.1rem]">
  433. <div className="pb-[.1rem] text-center text-[.14rem] font-bold">
  434. Termos e Condições
  435. </div>
  436. </div>
  437. <ul className={styles.introboxDesc}>
  438. <li>
  439. Todas as ofertas são liquidadas em reais (BRL - R$) e
  440. seguem o horário oficial de Brasília.
  441. </li>
  442. <li>
  443. Cada jogador, domicílio, endereço, e-mail, número de
  444. telefone, método de pagamento (mesmo cartão de
  445. débito/crédito ou conta bancária) e endereço IP são
  446. utilizados para verificação.
  447. </li>
  448. <li>
  449. Caso seja identificado que qualquer grupo ou indivíduo
  450. esteja abusando dos benefícios oferecidos pela empresa,
  451. esta reserva-se o direito de suspender ou cancelar o
  452. saldo do grupo envolvido.
  453. </li>
  454. </ul>
  455. </div>
  456. </div>
  457. </div>
  458. </div>
  459. </div>
  460. </div>
  461. <GlobalNotify
  462. amount={amount}
  463. visible={visible}
  464. onChange={() => setVisible(false)}
  465. deraction={5000}
  466. ></GlobalNotify>
  467. </div>
  468. );
  469. };
  470. export default Page;